package cn.qicaiwang.open.websocket.endpointer;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.qicaiwang.open.common.constant.Constants;
import cn.qicaiwang.open.common.entity.LoginUser;

import cn.qicaiwang.open.common.entity.Message;
import cn.qicaiwang.open.common.entity.MessageBody;
import cn.qicaiwang.open.common.enums.MessageBodyTypeEnum;
import cn.qicaiwang.open.common.enums.MessageEventEnum;
import cn.qicaiwang.open.common.enums.MessageTypeEnum;
import cn.qicaiwang.open.common.enums.ResultStatusCodeEnum;
import cn.qicaiwang.open.common.exception.BusinessException;
import cn.qicaiwang.open.websocket.common.Constant;
import cn.qicaiwang.open.websocket.utils.MessageUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;

/**
 * WebSocket服务处理类
 */
@Slf4j
@Component
public class CrmWebSocketHandler implements WebSocketHandler {
	@Autowired
	private RabbitTemplate rabbitTemplate;

	/**
	 * 1. 客户端成功建立连接时触发
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		System.out.println("客户端成功建立连接=>" + session.getId());
		// 在ws服务类中任何位置都可以使用以下取值
		System.out.println("登录用户：" + session.getAttributes().get(Constant.WS_CONTEXT_HOLDER));

		LoginUser loginUser = (LoginUser) session.getAttributes().get(Constant.WS_CONTEXT_HOLDER);
		// 存储所有客户端的WebSocketSession
		Constant.pool.put(loginUser.getId(), session);

		MessageBody body = new MessageBody();
		body.setType(MessageBodyTypeEnum.online.name());
		body.setContent(JSON.toJSONString(Constant.onlines()));

		Message message = Message.builder()
				.id(IdUtil.getSnowflakeNextIdStr())
				.title("上线通知")
				.event(MessageEventEnum.notice.name())
				.msgType(MessageTypeEnum.text.name())
				.fromUserId("-1")
				.message(body)
				.build();

		MessageUtil.sendAllMessage(message);
	}

	/**
	 * 2. 接收客户端数据时触发
	 */
	@Override
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
		System.out.println("接收客户端数据=>" + message.getPayload().toString());
		String messageJson = message.getPayload().toString();
		Message sendMessage = JSON.parseObject(messageJson, Message.class);
		if(StrUtil.isBlank(sendMessage.getFromUserId()) || StrUtil.isBlank(sendMessage.getToUserId())){
			throw new BusinessException(ResultStatusCodeEnum.PARAM_REQUIRE_ERROR);
		}

		// 给客户端回一句话意思意思,随便给客户端发数据
		MessageBody body = new MessageBody();
		body.setType(MessageBodyTypeEnum.message.name());
		body.setContent(sendMessage.getMessage().getContent());

		Message replyMessage = Message.builder()
				.id(IdUtil.getSnowflakeNextIdStr())
				.title("您有新消息通知")
				.event(MessageEventEnum.message.name())
				.msgType(sendMessage.getMsgType())
				.fromUserId(sendMessage.getFromUserId())
				.toUserId(sendMessage.getToUserId())
				.message(body)
				.build();

		rabbitTemplate.convertAndSend(Constants.RABBITMQ_DEFAULT_DIRECT_EXCHANGE, Constants.RABBITMQ_DEFAULT_DIRECT_ROUTING, replyMessage);
	}

	/**
	 * 3. 通信异常时触发
	 */
	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		log.error("通信异常=>" + session.getId());
	}

	/**
	 * 4.客户端关闭连接时触发
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
		System.out.println("客户端关闭连接=>" + session.getId());
		LoginUser loginUser = (LoginUser) session.getAttributes().get(Constant.WS_CONTEXT_HOLDER);
		// 移除通行关闭的客户端
		Constant.pool.remove(loginUser.getId());

		MessageBody body = new MessageBody();
		body.setType(MessageBodyTypeEnum.offline.name());
		body.setContent(JSON.toJSONString(Constant.onlines()));

		Message message = Message.builder()
				.id(IdUtil.getSnowflakeNextIdStr())
				.title("下线通知")
				.event(MessageEventEnum.notice.name())
				.msgType(MessageTypeEnum.text.name())
				.fromUserId("-1")
				.message(body)
				.build();
		MessageUtil.sendAllMessage(message);
	}

	/**
	 * 是否支持分段传输
	 */
	@Override
	public boolean supportsPartialMessages() {
		return false;// 一次输出完毕
	}

	/**
	 * 6. 服务器主动关闭通信
	 * @param webSocketSession
	 * @param msg
	 */
	public void close(WebSocketSession webSocketSession, String msg) {
		try {
			webSocketSession.close();

			MessageBody body = new MessageBody();
			body.setType(MessageBodyTypeEnum.offline.name());
			body.setContent(JSON.toJSONString(Constant.onlines()));

			Message message = Message.builder()
					.id(IdUtil.getSnowflakeNextIdStr())
					.title("下线通知")
					.event(MessageEventEnum.notice.name())
					.msgType(MessageTypeEnum.text.name())
					.fromUserId("-1")
					.message(body)
					.build();
			MessageUtil.sendAllMessage(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
